package com.example.layoutmanagerdemo.layoutmanger.path;

import android.graphics.Path;
import android.graphics.PathMeasure;

import androidx.annotation.FloatRange;

/**
 * Created by wangxingsheng on 2020/6/8.
 * desc:
 */
public class Keyframes {
    private static final float PRECISION = 0.5f;
    private int mNumPoints = 0;
    private float[] mX; //Path的所有x轴坐标点
    private float[] mY; //Path的所有y轴坐标点
    private float[] mAngle; //Path上每一个坐标所对应的角度
    private PathMeasure pathMeasure;

    public Keyframes(Path path) {
        initPath(path);
    }

    private void initPath(Path path) {
        pathMeasure = new PathMeasure(path, false);
        float pathLength = pathMeasure.getLength();
        mNumPoints = (int) (pathLength / PRECISION) + 1;
        mX = new float[mNumPoints];
        mY = new float[mNumPoints];
        mAngle = new float[mNumPoints];
        //临时存放坐标点
        float[] position = new float[2];
        //临时存放正切值
        float[] tangent = new float[2];
        //当前距离
        float distance;
        for (int i = 0; i < mNumPoints; ++i) {
            //更新当前距离
            distance = (i * pathLength) / (mNumPoints - 1);
            //根据当前距离获取对应的坐标点和正切值
            pathMeasure.getPosTan(distance, position, tangent);
            mX[i] = position[0];
            mY[i] = position[1];
            //利用反正切函数得到角度
            mAngle[i] = fixAngle((float) (Math.atan2(tangent[1], tangent[0]) * 180F / Math.PI) - 90F);
        }
    }

    /**
     * 调整角度，使其在0 ~ 360之间
     *
     * @param rotation 当前角度
     * @return 调整后的角度
     */
    private float fixAngle(float rotation) {
        float angle = 360F;
        if (rotation < 0) {
            rotation += angle;
        }
        if (rotation > angle) {
            rotation %= angle;
        }
        return rotation;
    }

    /**
     * 根据传入的百分比来获取对应的坐标点和角度
     *
     * @param fraction 当前百分比: 0~1
     */
    public PosTan getValue(@FloatRange(from = 0F, to = 1F) float fraction) {
        //超出范围的直接返回空
        if (fraction >= 1F || fraction < 0) {
            return null;
        } else {
            PosTan mTemp = new PosTan();
            int index = (int) (mNumPoints * fraction);
            //更新temp的内部值
            mTemp.set(mX[index], mY[index], mAngle[index]);
            mTemp.setIndex(index);
            mTemp.setFraction(fraction);
            return mTemp;
        }
    }

    public float getPathLength() {
        return pathMeasure.getLength();
    }
}

